/*
 * ECARX Technology Limited is the owner of the copyright and the trade secret of this software.
 * Without permission, no one has the right to obtain, disclose or use this software in any way.
 */

package com.ecarx.systemui.plugin.ui.dialog;

import static android.media.AudioManager.ADJUST_MUTE;
import static android.media.AudioManager.ADJUST_UNMUTE;
import static android.media.AudioManager.STREAM_VOICE_CALL;
import static android.media.AudioSystem.STREAM_ASSISTANT;
import static android.media.AudioSystem.STREAM_MUSIC;
import static android.media.AudioSystem.STREAM_NAVI_TTS;
import static android.media.AudioSystem.STREAM_TTS;

import android.annotation.SuppressLint;
import android.car.media.CarAudioManager;
import android.content.Context;
import android.graphics.PixelFormat;

import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.SeekBar;

import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;

import com.ecarx.systemui.plugin.AppConstants;
import com.ecarx.systemui.plugin.R;
import com.ecarx.systemui.plugin.common.CommonUtils;
import com.ecarx.systemui.plugin.controller.CarVoiceController;
import com.ecarx.systemui.plugin.ui.dialog.base.AutoCloseDialog;
import com.ecarx.systemui.plugin.ui.dialog.base.DialogManager;
import com.ecarx.systemui.plugin.utils.DensityUtils;
import com.ecarx.systemui.plugin.utils.LogUtils;

public class VolumeDialog extends AutoCloseDialog implements View.OnClickListener {

    private static final String TAG = "VolumeDialogTag";

    private final CarAudioManager carAudioManager;
    private final CarVoiceController carVoiceController;

    private static final int SEEKBAR_MEDIA_TAG = 1;
    private static final int SEEKBAR_NAVI_TAG = 2;
    private static final int SEEKBAR_VOICE_TAG = 3;
    private static final int SEEKBAR_PHONE_TAG = 4;

    private View rootView;
    private SeekBar seekBarMedia;
    private SeekBar seekBarNavi;
    private SeekBar seekBarVoice;
    private SeekBar seekBarPhone;
    private ImageView ivTopMedia;
    private ImageView ivTopNavi;
    private ImageView ivTopPhone;
    private ImageView ivTopVoice;
    final int DIALOG_DELAY_TIME = 150;
    final int MSG_DELAY_TIME = 50;
    final int WHAT_SET_MEDIA = 1001;
    final int WHAT_SET_NAVI = 1002;
    final int WHAT_SET_VOICE = 1003;
    final int WHAT_SET_PHONE = 1004;

    private final Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            int what = msg.what;
            switch (what) {
                case WHAT_SET_MEDIA:
                    int setMediaVolume = msg.arg1;
                    LogUtils.d(TAG, "设置媒体音量:" + setMediaVolume);
                    reallySetVolume(carVoiceController.getMediaGroupId(), setMediaVolume);
                    break;
                case WHAT_SET_NAVI:
                    int setNaviVolume = msg.arg1;
                    LogUtils.d(TAG, "设置导航音量:" + setNaviVolume);
                    reallySetVolume(carVoiceController.getNaviGroupId(), setNaviVolume);
                    break;
                case WHAT_SET_VOICE:
                    int setVoiceVolume = msg.arg1;
                    LogUtils.d(TAG, "设置语音音量:" + setVoiceVolume);
                    reallySetVolume(carVoiceController.getVoiceGroupId(), setVoiceVolume);
                    break;
                case WHAT_SET_PHONE:
                    int setPhoneVolume = msg.arg1;
                    LogUtils.d(TAG, "设置电话音量:" + setPhoneVolume);
                    reallySetVolume(carVoiceController.getPhoneGroupId(), setPhoneVolume);
                    break;

            }
        }
    };

    public VolumeDialog(@NonNull Context context) {
        this(context, 0);
    }

    public VolumeDialog(@NonNull Context context, int themeResId) {
        super(context, themeResId);
        carVoiceController = CarVoiceController.getCarVoiceController();
        carAudioManager = carVoiceController.getCarAudioManager();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LogUtils.i(TAG, "onCreate");
        setContentView(R.layout.dialog_volume);
        initView();
        initConfig();
    }

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        LogUtils.i(TAG, "onAttachedToWindow");
    }

    @Override
    public void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        LogUtils.i(TAG, "onDetachedFromWindow");
    }

    private void initView() {
        rootView = findViewById(R.id.root_view);
        rootView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startTimingClose();
            }
        });
        findViewById(R.id.iv_close).setOnClickListener(v -> delayedDismiss());

        ivTopMedia = findViewById(R.id.iv_left_media);
        ivTopNavi = findViewById(R.id.iv_left_navi);
        ivTopPhone = findViewById(R.id.iv_left_phone);
        ivTopVoice = findViewById(R.id.iv_left_voice);

        ivTopMedia.setOnClickListener(this);
        ivTopNavi.setOnClickListener(this);
        ivTopPhone.setOnClickListener(this);
        ivTopVoice.setOnClickListener(this);

        seekBarMedia = findViewById(R.id.seek_bar_media);
        seekBarMedia.setMax(carVoiceController.getMediaMaxVolume());
        seekBarMedia.setTag(SEEKBAR_MEDIA_TAG);

        seekBarNavi = findViewById(R.id.seek_bar_navi);
        seekBarNavi.setMax(carVoiceController.getNaviMaxVolume());
        seekBarNavi.setTag(SEEKBAR_NAVI_TAG);

        seekBarVoice = findViewById(R.id.seek_bar_voice);
        seekBarVoice.setMax(carVoiceController.getVoiceMaxVolume());
        seekBarVoice.setTag(SEEKBAR_VOICE_TAG);

        seekBarPhone = findViewById(R.id.seek_bar_phone);
        seekBarPhone.setMax(carVoiceController.getPhoneMaxVolume());
        seekBarPhone.setTag(SEEKBAR_PHONE_TAG);

        seekBarMedia.setOnSeekBarChangeListener(onSeekBarChangeListener);
        seekBarNavi.setOnSeekBarChangeListener(onSeekBarChangeListener);
        seekBarVoice.setOnSeekBarChangeListener(onSeekBarChangeListener);
        seekBarPhone.setOnSeekBarChangeListener(onSeekBarChangeListener);

        showAllInitVoice();
    }

    public void showAllInitVoice() {
        showInitSeekBar(SEEKBAR_MEDIA_TAG);
        showInitSeekBar(SEEKBAR_NAVI_TAG);
        showInitSeekBar(SEEKBAR_VOICE_TAG);
        showInitSeekBar(SEEKBAR_PHONE_TAG);
    }

    private void showInitSeekBar(int flag) {
        if (carAudioManager == null) {
            return;
        }
        switch (flag) {
            case SEEKBAR_MEDIA_TAG:
                int mediaGroupId = carVoiceController.getMediaGroupId();
                int mediaVolume = carAudioManager.getGroupVolume(mediaGroupId);
                boolean isMute = carVoiceController.isStreamMute(STREAM_MUSIC);
                seekBarMedia.setProgress(isMute ? 0 : mediaVolume);
                checkTopIcon(mediaGroupId, mediaVolume);
                break;
            case SEEKBAR_NAVI_TAG:
                int naviGroupId = carVoiceController.getNaviGroupId();
                int naviVolume = carAudioManager.getGroupVolume(naviGroupId);
                boolean isMuteNavi = carVoiceController.isStreamMute(STREAM_NAVI_TTS);
                LogUtils.i(TAG, "SEEKBAR_NAVI_TAG naviGroupId" + naviGroupId + ", naviVolume ="+ naviVolume + ", isMuteNavi =" + isMuteNavi);
                seekBarNavi.setProgress(isMuteNavi ? 0 : naviVolume);
                checkTopIcon(naviGroupId, naviVolume);
                break;
            case SEEKBAR_VOICE_TAG:
                int voiceGroupId = carVoiceController.getVoiceGroupId();
                int voiceVolume = carAudioManager.getGroupVolume(voiceGroupId);
                boolean isMuteVoice = carVoiceController.isStreamMute(STREAM_ASSISTANT);
                seekBarVoice.setProgress(isMuteVoice ? 0 : voiceVolume);
                checkTopIcon(voiceGroupId, voiceVolume);
                break;
            case SEEKBAR_PHONE_TAG:
                int phoneGroupId = carVoiceController.getPhoneGroupId();
                int phoneVolume = carAudioManager.getGroupVolume(phoneGroupId);
                boolean isMutePhone = carVoiceController.isStreamMute(STREAM_VOICE_CALL);
                seekBarPhone.setProgress(isMutePhone? 0 : phoneVolume);
                checkTopIcon(phoneGroupId, phoneVolume);
                break;
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    private void initConfig() {
        Window window = getWindow();
        if (window != null) {
            WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                    WindowManager.LayoutParams.MATCH_PARENT,
                    WindowManager.LayoutParams.MATCH_PARENT,
                    AppConstants.PLUGIN_DIALOG_TYPE,
                    android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
                            android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN |
                            android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
                            android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
                            android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                    PixelFormat.TRANSPARENT);
            params.gravity = Gravity.START | Gravity.TOP;
            params.y = DensityUtils.dp2px(94);
            window.setAttributes(params);
            WindowManager.LayoutParams attributes = window.getAttributes();
            attributes.height = DensityUtils.getScreenHeight() - DensityUtils.dp2px(94);
            window.setAttributes(attributes);
            window.getDecorView().setOnTouchListener((v, event) -> {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    dismiss();
                }
                return false;
            });
            FrameLayout.LayoutParams layoutParams =
                    (FrameLayout.LayoutParams) rootView.getLayoutParams();
            layoutParams.gravity = Gravity.CENTER;
            rootView.setLayoutParams(layoutParams);
        }
    }

    private final SeekBar.OnSeekBarChangeListener onSeekBarChangeListener =
            new SeekBar.OnSeekBarChangeListener() {
                @Override
                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                    Object tag = seekBar.getTag();
                    LogUtils.d(TAG, "onProgressChanged progress:" + progress
                            + ", fromUser:" + fromUser + ", tag:" + tag);
                    if (tag instanceof Integer) {
                        int proTag = (int) tag;
                        if (fromUser && carAudioManager != null && carVoiceController != null) {
                            updateProgress(progress, proTag);
                        }
                    }
                }

                @Override
                public void onStartTrackingTouch(SeekBar seekBar) {
                    LogUtils.d(TAG, "onStartTrackingTouch start Touch");
                    cancelTimingClose();
                }

                @Override
                public void onStopTrackingTouch(SeekBar seekBar) {
                    LogUtils.d(TAG, "onStopTrackingTouch stop up");
                    startTimingClose();
                }
            };

    @SuppressLint("NonConstantResourceId")
    @Override
    public void onClick(View view) {
        if (CommonUtils.isFastClick()) {
            LogUtils.d(TAG, "静音连点 未超过250毫秒");
            return;
        }
        switch (view.getId()) {
            case R.id.iv_left_media:
                muteVoice(STREAM_MUSIC, SEEKBAR_MEDIA_TAG);
                break;
            case R.id.iv_left_navi:
                muteVoice(STREAM_NAVI_TTS, SEEKBAR_NAVI_TAG);
                break;
            case R.id.iv_left_phone:
                muteVoice(STREAM_VOICE_CALL, SEEKBAR_PHONE_TAG);
                break;
            case R.id.iv_left_voice:
                muteVoice(STREAM_ASSISTANT, SEEKBAR_VOICE_TAG);
                break;
        }

    }

    private void muteVoice(int streamType, int seekBarTag) {
        boolean isMute = carVoiceController.isStreamMute(streamType);
        LogUtils.d(TAG, " streamType : " + streamType + "--isMute:" + isMute);
        //mAudioManager.setStreamMute(streamType, !isMute);
        int groupId = carVoiceController.getGroupIdByStreamType(streamType);
        carAudioManager.setGroupVolume(groupId, 0, isMute ? ADJUST_UNMUTE : ADJUST_MUTE);
        LogUtils.d(TAG,"setStreamMuteAll isMute: " + isMute + ", groupId = " + groupId);

        isMute = carVoiceController.isStreamMute(streamType);
        LogUtils.d(TAG, "--isMute:" + isMute);
        showInitSeekBar(seekBarTag);
    }


    private void reallySetVolume(int groupId, int volume) {
        LogUtils.i(TAG, "reallySetVolume groupId =" + groupId + ", volume =" + volume);
        carAudioManager.setGroupVolume(groupId, volume, AudioManager.FLAG_PLAY_SOUND);
        checkTopIcon(groupId, volume);
    }

    private void checkTopIcon(int groupId, int volume) {
        if (groupId == carVoiceController.getMediaGroupId()) {
            boolean isMute = carVoiceController.isStreamMute(STREAM_MUSIC);
            LogUtils.d(TAG, "checkTopIcon isMute Media =" + isMute + "， volume = " + volume);
            ivTopMedia.setImageDrawable(AppCompatResources.getDrawable(
                    getContext(), (volume == 0 || isMute) ? R.drawable.dialog_top_media_mute
                            : R.drawable.dialog_top_media)
            );
        } else if (groupId == carVoiceController.getNaviGroupId()) {
            boolean isMute = carVoiceController.isStreamMute(STREAM_NAVI_TTS);
            LogUtils.d(TAG, "checkTopIcon isMute TTS =" + isMute);
            ivTopNavi.setImageDrawable(AppCompatResources.getDrawable(
                    getContext(), (volume == 0 || isMute)  ? R.drawable.dialog_top_navigation_mute
                            : R.drawable.dialog_top_navigation)
            );
        } else if (groupId == carVoiceController.getVoiceGroupId()) {
            boolean isMute = carVoiceController.isStreamMute(STREAM_ASSISTANT);
            LogUtils.d(TAG, "checkTopIcon isMute Voice =" + isMute);
            ivTopVoice.setImageDrawable(AppCompatResources.getDrawable(
                    getContext(), (volume == 0 || isMute) ? R.drawable.dialog_top_voice_mute
                            : R.drawable.dialog_top_voice)
            );
        } else if (groupId == carVoiceController.getPhoneGroupId()) {
            boolean isMute = carVoiceController.isStreamMute(STREAM_VOICE_CALL);
            LogUtils.d(TAG, "checkTopIcon isMute Phone =" + isMute);
            ivTopPhone.setImageDrawable(AppCompatResources.getDrawable(
                    getContext(), (volume == 0 || isMute)  ? R.drawable.dialog_top_phone_mute
                            : R.drawable.dialog_top_phone)
            );
        }
    }

    private void updateProgress(int progress, int proTag) {
        switch (proTag) {
            case SEEKBAR_MEDIA_TAG:
                sendSetVolumeMsg(WHAT_SET_MEDIA, progress);
                break;
            case SEEKBAR_NAVI_TAG:
                sendSetVolumeMsg(WHAT_SET_NAVI, progress);
                break;
            case SEEKBAR_VOICE_TAG:
                sendSetVolumeMsg(WHAT_SET_VOICE, progress);
                break;
            case SEEKBAR_PHONE_TAG:
                sendSetVolumeMsg(WHAT_SET_PHONE, progress);
                break;
        }
    }

    private void sendSetVolumeMsg(int what, int progress) {
        handler.removeMessages(what);
        Message obtain = Message.obtain();
        obtain.what = what;
        obtain.arg1 = progress;
        handler.sendMessageDelayed(obtain, MSG_DELAY_TIME);
    }

    @Override
    protected void delayedDismiss() {
        dismiss();
    }

    @Override
    public void dismiss() {
        rootView.startAnimation(outAnimation);
        rootView.postDelayed(() -> {
            VolumeDialog.super.dismiss();
            DialogManager.getDialogManager().cleanVolumeDialog();
        }, DIALOG_DELAY_TIME);
    }


    @Override
    protected boolean isAutoDismiss() {
        return false;
    }
}
